/*
 *  $Id: XmlCardExporter.cs 1215 2010-11-24 14:50:50Z thenn.erannor $
 *	This file is a part of Ragima CCG.
 *	(C) 2008-2010 Ragima development group.
 *
 *	Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;

namespace Ragima {
    public class XmlCardExporter : ICardExporter {
        public void Export(Stream stream, IEnumerable<Card> cards) {
            using (var writer = new XmlTextWriter(stream, Encoding.UTF8)) {
                writer.Formatting = Formatting.Indented;
                writer.Indentation = 2;
                Export(writer, cards);
            }
        }

        private void Export(XmlTextWriter writer, IEnumerable<Card> cards) {
            writer.WriteStartDocument();
            writer.WriteStartElement("cards");
            foreach (var card in cards) {
                writer.WriteStartElement("card");
                Export(writer, card);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
            writer.WriteEndDocument();
        }

        private void Export(XmlTextWriter writer, Card card) {
            writer.WriteAttributeString("id", card.Id);
            writer.WriteAttributeString("name", card.Name.ToString());
            writer.WriteAttributeString("element", card.Element.Id);
            writer.WriteAttributeString("type", card.CardType.ToString());
            writer.WriteAttributeString("maxcount", card.MaxCount.ToString());
            writer.WriteAttributeString("weight", card.Weight.ToString());
            if (card is CreatureCard) {
                var cr = card as CreatureCard;
                writer.WriteStartElement("creature");
                writer.WriteAttributeString("damage", cr.Damage.ToString());
                writer.WriteAttributeString("health", cr.Health.ToString());
                if (!(cr.Race is Races.Unique))
                    writer.WriteAttributeString("race", cr.Race.Name.ToString());
                writer.WriteEndElement();
            }
            writer.WriteStartElement("conditions");
            foreach (var cond in card.GetConditions()) {
                if (cond is MeditationCondition) {
                    writer.WriteStartElement("meditation");
                    writer.WriteAttributeString("value", (cond as MeditationCondition).Value.ToString());
                    writer.WriteEndElement();
                }
            }
            writer.WriteEndElement();
            writer.WriteStartElement("mana");
            foreach (var element in ElementType.AllElements)
                if (card.ManaCost[element] != 0)
                    writer.WriteAttributeString(element.Id, card.ManaCost[element].ToString());
            writer.WriteEndElement();
            writer.WriteElementString("description", card.DescriptionText);
            if (card is SummonableCard) {
                var collector = new CardCollector(card as SummonableCard);
                if (collector.Abilities.Count > 0) {
                    writer.WriteStartElement("abilities");
                    foreach (var ability in collector.Abilities) {
                        writer.WriteStartElement("ability");
                        writer.WriteAttributeString("id", ability.Id);
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                if (collector.Affects.Count > 0) {
                    writer.WriteStartElement("affects");
                    foreach (var affect in collector.Affects) {
                        writer.WriteStartElement("affect");
                        writer.WriteAttributeString("id", affect.Id);
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
            }
        }

        private class CardCollector: ICollector<AbilityCard>, ICollector<Affect> {
            private List<AbilityCard> _abilities;
            private List<Affect> _affects;

            public CardCollector(SummonableCard card) {
                _abilities = new List<AbilityCard>();
                _affects = new List<Affect>();
                card.CollectAbilities(this);
                card.CollectNaturalAffects(this);
            }

            public List<AbilityCard> Abilities {
                get { return _abilities; }
            }
            public List<Affect> Affects {
                get { return _affects; }
            }

            void ICollector<AbilityCard>.Add(AbilityCard item) {
                _abilities.Add(item);
            }
            void ICollector<AbilityCard>.Add<T>() {
                _abilities.Add(CardManager.GetAbility<T>());
            }
            void ICollector<Affect>.Add(Affect item) {
                _affects.Add(item);
            }
            void ICollector<Affect>.Add<T>() {
                _affects.Add(new T());
            }
        }
    }
}
